'''oto/server.py

This module contains the OtoServer class.
'''

__authors__ = ['Ryan Rousseau <ryan.rousseau@gmail.com>']
__license__ = '''Oranges to Oranges
Copyright (C) 2006  Ryan Rousseau

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
'''

import sys
import os
import time
import threading

# Pyro imports #

import Pyro.core
import Pyro.naming
import Pyro.util
from Pyro.errors import PyroError, NamingError
from Pyro.ext.daemonizer import Daemonizer
from Pyro.EventService import Server

# quizzical imports
from constants import *
from identifier import *

__all__ = ['OtoServer']

# get ip
# TODO research a better way to find the ip address
fp = os.popen('ifconfig')
for line in fp:
    line = line.strip()
    if line.startswith('inet addr'):
        ip = line.split(':')[1].split()[0]
        if ip != '127.0.0.1':
            break
fp.close()
del fp

Pyro.config.PYRO_NS_HOSTNAME = ip

class _NullDevice(object):
    def write(self, s):
        pass

class OtoServer(Daemonizer):
    '''OtoServer()

The QuizzicalServer starts the Pyro NS and ES and starts an identifier
object on the NS.
'''
    def __init__(self):
        Daemonizer.__init__(self)

    def become_daemon(self, root_dir='/tmp'):
        if os.fork() != 0:  # launch child and ...
            os._exit(0)  # kill off parent
        os.setsid()
        os.chdir(root_dir)
        os.umask(0)
        if os.fork() != 0: # fork again so we are not a session leader
            os._exit(0)
        sys.stdin.close()
        sys.__stdin__ = sys.stdin
        sys.stdout.close()
        sys.stdout = sys.__stdout__ = _NullDevice()
        sys.stderr.close()
        sys.stderr = sys.__stderr__ = _NullDevice()

        # the following lines are killing my server, don't know why
        # yet, but everything seems to work when they are commented
        #for fd in range(1024):
        #    try:
        #        os.close(fd)
        #    except OSError:
        #        pass

    def main_loop(self):
        Pyro.core.initClient(banner=0)
        Pyro.core.initServer(banner=0)

        # if no Name Server is running, start one
        status = os.popen('pyro-nsd status').readline().strip()
        if 'Server is not running.' == status:
            os.system('pyro-nsd start -n %s > /dev/null' % Pyro.config.PYRO_NS_HOSTNAME)
            time.sleep(5)

        # if no Event Service is running, start one
        status = os.popen('pyro-esd status').readline().strip()
        if 'Server is not running.' == status:
            os.system('pyro-esd start -n %s > /dev/null' % Pyro.config.PYRO_NS_HOSTNAME)

        try:
            locator = Pyro.naming.NameServerLocator()
            ns = locator.getNS(host=Pyro.config.PYRO_NS_HOSTNAME)
        except PyroError, pe:
            return 1

        try:
            ns.createGroup(PYRO_GROUP)
        except NamingError:
            pass

        try:
            ns.unregister(IDENT_NAME)
        except NamingError, ne:
            pass

        daemon = Pyro.core.Daemon(host=ip)
        daemon.useNameServer(ns)
        daemon.connect(Identifier(), IDENT_NAME)
        try:
            daemon.requestLoop()
        except KeyboardInterrupt:
            ns.unregister(IDENT_NAME)
